/*
Dependencies: prototype
Requirements:
CREATING TAB WITH MARK UP
The tab must have structure: <div><ul><li class='tab'><a id=''><div></div></a>...</li>....</ul></div>

To specify the data source:
href = "@ajax <url_string>" : load data from <url_string> when tab is clicked
href = "@id <id_string>": load data from element with <id_string> when tab is clicked

To enable preload of data when using ajax datasource:
href = "@preload @ajax <url_string>"

THIS VERSION IS NOT COMPLETED USERS CURRENTLY CAN'T CREATE NEW TAB ITEM USING JAVASCRIPT 
*/

function TabItem() {
	// the content of the tab
	this.tabContent = '';
	this.tabContentElement = null;
	this.tabIndex = -1;
	this.tabId = '';
	this.tabElement = null;
	this.preload = false;	// default: not allowing preloading of the tab content (in the case data source is ajax)
	this.dataSourceType = '@id';	// default: load data from a HTML element.
	this.dataSourceId = null;
	this.isActive = false;
	this.queryMethod = "post";
	this.tabDataLoaded = false;
	this.attached = false;	// whether this tab is attached to the document
	this.dataLoading = false;
	
	this.onStartLoading = null;
	this.onDataSuccess = null;
	this.onDataFailure = null;
	this.onTabAttached = null;
}

TabItem.prototype.setContentElement = function(content) {
	this.tabContentElement = content;
}

TabItem.prototype.attach = function(parentElement, show) {
	var up = this.tabContentElement.up();
	if (up != parentElement) {
		if (up) this.tabContentElement.remove();
		parentElement.appendChild(this.tabContentElement);
	}
	this.attached = true;
	if (!show) this.tabContentElement.style.display = "none";
}

TabItem.prototype.setTabId = function(id) {
	this.tabId = id;
	this.tabElement = $(id);
}

TabItem.prototype.setTabIndex = function(index) {
	this.tabIndex = index;
}

TabItem.prototype.setTabElement = function(element) {
	this.tabElement = element;
	if (element.id != this.tabId) this.tabId = element.id;
}

TabItem.prototype.setDataSource = function(sourceType, sourceId) {
	this.dataSourceType = sourceType;
	this.dataSourceId = sourceId;
	if (this.preload || sourceType == '@id') this.loadTabData();	// if preload is set, load the tab data
}

TabItem.prototype.setPreload = function() {
	this.preload = true;
	if (this.dataSourceType && this.dataSourceId)	// if this two value is set, load the data
		this.loadTabData();	// load the data
}

/*
this function load the data and store in the object.
*/
TabItem.prototype.loadTabData = function() {
	if (this.dataLoading) return;
	this.dataLoading = true;
	if (this.onStartLoading) this.onStartLoading();
	if (this.dataSourceType == '@id') {
		var content = $(this.dataSourceId);
		if (content) {
			this.tabContentElement = content;
			this.tabDataLoaded = true; // must put before onDataSuccess invoke
			if (this.onDataSuccess) this.onDataSuccess(this);
		} else if (this.onDataFailure) this.onDataFailure(this);
		this.dataLoading = false;
	} else if (this.dataSourceType == '@ajax') {
		this.loadAjaxData();
	}
}
/*
This function load data in the case of data source is @ajax
*/
TabItem.prototype.loadAjaxData = function() {
	var successFunc = function(transport) { 
		if (this.tabContentElement == null) 
			this.tabContentElement = new Element("div");
		this.tabContentElement.innerHTML = transport.responseText;		// store the content
		this.tabDataLoaded = true;
		if (this.onDataSuccess) this.onDataSuccess(this);
		this.dataLoading = false;
	}
	var failureFunc = function(transport) { 
		if(this.onDataFailure) this.onDataFailure(transport);
		this.dataLoading = false;
	}
	new Ajax.Request(this.dataSourceId,	{
		method: this.queryMethod,
		onSuccess: successFunc.bind(this),
		onFailure: failureFunc.bind(this)
	});
}

TabItem.prototype.setQueryMethod = function(method) {
	this.queryMethod = method;
}

/*********************
Tab list object, control the behavior of the tab items. 
*********************/

function Tab(tabListId, tabBodyId, options) {
	this.tabItemList = new Array();
	this.tabItemNameIndex = new Array();
	this.activeTabIndex = -1;
	this.onTabDisplay = null;
	
	if (tabBodyId != null)	// tabBodyId is the id of the HTMLelement in where content is loaded.
		this.tabBody = $(tabBodyId);
	 else this.tabBody = new Element('div');
	
	if (tabListId != null) {	// create tab from markup
		this.tabListId = tabListId;
		this.tabList = $(tabListId);
		this.tabUL = this.tabList.down('ul');
		
		if (!this.tabUL) return false;
		this.tabA = this.tabUL.select('li.tab a');	// get all the A elements which is the descendant of li.tab
		var i = 0;
		for (i = 0; i < this.tabA.length; i++) {
			var tab_id = this.tabA[i].id;
			var tab_href = this.tabA[i].href;
			
			var tab_item = new TabItem();
			tab_item.setTabElement(this.tabA[i]);
			tab_item.setTabIndex(i);
			this.trapTabItemEvents(tab_item);
				
			if (tab_href != '')	{ // if there is href, check if we can take the content immediately
				var pos = tab_href.indexOf('@');
				if (pos > 0) tab_href = unescape(tab_href.substring(pos));
				
				var tokens = $w(tab_href);
				
				var j = 0;var increased;
				while (j < tokens.length) {
					increased = 0;
					if (tokens[j] == '@preload') tab_item.setPreload();
					if (tokens[j] == '@id' || tokens[j] == '@ajax') {
						tab_item.setDataSource(tokens[j], tokens[j+1]);
						increased++;
					}
					if (tokens[j] == '@get') tab_item.setQueryMethod('get');	// token @get must always precede token @id
					j += (1+increased);
				}
			}
			this.addTabItem(tab_item);
			this.tabA[i].href = 'javascript:';
			this.tabA[i].onclick = this.onTabClickHandle.bind(this, i);
		}
	} else {
	}
}

/*
This function reattach the <A> tags from the documents to the tab object
This function can be used to reattach the tab items if the HTML contains the tabs are 
moved around in the documents but the inside is not changed (both content of each tab and ids of the tabs).
*/
Tab.prototype.reattach = function() {
	this.tabA.clear();
	for (var i = 0; i < this.tabItemList.length; i++) {
		var tab_item = this.tabItemList[i];
		tab_item.setTabId(tab_item.tabId);	// refresh the tab element
		this.tabA[i] = $(tab_item.tabId);
		this.tabA[i].onclick = this.onTabClickHandle.bind(this, i);
	}
	this.tabBody = $(this.tabBodyId);
}

Tab.prototype.trapTabItemEvents = function(tab_item) {
	tab_item.onStartLoading = this._onStartLoading.bind(this, tab_item);
	tab_item.onDataSuccess = this._onDataSuccess.bind(this, tab_item);
	tab_item.onDataFailure = this._onDataFailure.bind(this, tab_item);
	tab_item.onTabAttached = this._onTabAttached.bind(this, tab_item);
}

Tab.prototype.start = function(options) {
	this.processStartupOptions(options);
}

Tab.prototype.processStartupOptions = function(options) {
	
	if (!options) options = {defaultIndex:0};
	if (!options.defaultIndex && !options.defaultTab) options.defaultIndex = 0;
	
	if (options.loading || options.loadingElementID || options.loadingElement) {
		var tab_item = new TabItem();
		tab_item.setTabIndex(this.tabItemList.length);
		if (options.loadingElementID) tab_item.setDataSource('@id', options.loadingElementID);
		if (options.loadingElement) tab_item.setContentElement(options.loadingElement);
		if (options.loadingElementID || options.loadingElement) tab_item.attach(this.tabBody, false);
		//this.addTabItem(tab_item);
		this.loadingMessage = tab_item;
	}
	
	if (options.defaultIndex || options.defaultTab || options.defaultIndex === 0) {
		var tab_item;
		if (options.defaultIndex >= 0) tab_item = this.tabItemList[options.defaultIndex];
		else tab_item = this.tabItemList[this.tabItemNameIndex[options.defaultTab]];
		if (tab_item) this.showTab(tab_item);
	}
}

Tab.prototype.showLoading = function() {
	if (!this.loadingMessage) return;
	this.loadingMessage.tabContentElement.style.display = '';
	if (this.activeTabIndex != -1) {
		var element = this.tabItemList[this.activeTabIndex].tabContentElement;
		if (element) element.style.display = 'none';
	}
}

Tab.prototype.hideLoading = function() {
	if (!this.loadingMessage) return;
	this.loadingMessage.tabContentElement.style.display = 'none';
	if (this.activeTabIndex != -1) {
		var element = this.tabItemList[this.activeTabIndex].tabContentElement;
		if (element) element.style.display = '';
	}
}

Tab.prototype.showTab = function(tab_item) {
	if (tab_item.isActive) return;	// already show this tab? return.
	if (this.activeTabIndex != -1 && this.activeTabIndex != tab_item.tabIndex) { // clear the old tab
		var oldTab = this.tabItemList[this.activeTabIndex];
		oldTab.tabElement.up('li').className = 'tab';
		oldTab.isActive = false;
		if (oldTab.tabContentElement) oldTab.tabContentElement.style.display = 'none';
		if (this.onTabChange) this.onTabChange(oldTab, tab_item);
	}
	this.activeTabIndex = tab_item.tabIndex;
	tab_item.tabElement.up('li').className = 'tab active';
	if (!tab_item.tabDataLoaded) {	// if the data is not already loaded
		this.showLoading();
		tab_item.loadTabData();
	} else if (!tab_item.attached) {
		tab_item.attach(this.tabBody, true);
	} else {
		// make sure the tabContent is available for
		tab_item.tabContentElement.style.display = '';
		this.hideLoading();
		if (this.onTabDisplay) this.onTabDisplay(tab_item);
		tab_item.isActive = true;
	}
}

Tab.prototype._onDataSuccess = function(tab_item) {
	var result = true;
	if (!tab_item.attached) tab_item.attach(this.tabBody, false);
	if (tab_item.tabIndex == this.activeTabIndex) this.showTab(tab_item);
	if (this.onDataSuccess) 
		result = this.onDataSuccess(tab_item);
	return result;
}

Tab.prototype._onDataFailure = function(tab_item) {
	var result = true;
	if (this.onDataFailure) 
		result = this.onDataFailure(tab_item);
	return result;
}

Tab.prototype._onStartLoading = function(tab_item) {
	var result = true;
	if (this.onStartLoading) result = this.onStartLoading(tab_item);
	return result;
}

Tab.prototype._onTabAttached = function(tab_item) {
	var result = true;
	if (this.onTabAttach) result = this.onStartLoading(tab_item);
	return result;
}

/*
This function listen to the click, display tab content
*/
Tab.prototype.onTabClickHandle = function(tabIndex) {
	var tab_item = this.tabItemList[tabIndex];
	this.showTab(tab_item);
}

Tab.prototype.addTabItem = function(tab_item) {
	this.tabItemList.push(tab_item);
	if (tab_item.tabId != null && tab_item.tabId != '') this.tabItemNameIndex[tab_item.tabId] = tab_item.tabIndex;
}

Tab.prototype.setTabItemContent = function() {
}

Tab.prototype.moveTo = function(tab) {
	if (tab.length > 0) {	// id string
		this.showTab(this.tabItemList[this.tabItemNameIndex[tab]]);
	} else {	// index
		this.showTab(this.tabItemList[tab]);
	}
}